package cn.udrm.elasticsearch.service.impl;

import cn.udrm.elasticsearch.fulltext.BuildFileIndex;
import cn.udrm.elasticsearch.fulltext.FileOperation;
import cn.udrm.elasticsearch.service.ExcuteFullTextService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 执行全文检索类
 */
@Slf4j
@Service("excuteFullTextService")
public class ExcuteFullTextServiceImpl implements ExcuteFullTextService {

    @Resource
    private BuildFileIndex buildFileIndex;

    /**
     * 执行全文检索
     * @param fileTypes：匹配的文件类型
     * @param indexRoot：扫描的文件路径，可以是多个以逗号隔开
     * @throws Exception
     */
    @Override
    public void start(String fileTypes,String indexRoot,int depth,String indexName,String docType) throws Exception {
        long start=System.currentTimeMillis();
        int count=0;
        List<File> fileList=new ArrayList<File>();
        List totalList=new CopyOnWriteArrayList();//索引文件总数
        List list=new CopyOnWriteArrayList();//检索文件总数
        int availableProcessors=Runtime.getRuntime().availableProcessors();
        int threads= 2*availableProcessors+1;
        String[] paths=indexRoot.split(",");
        for(String path:paths){
            log.info("=============path："+path);
            getFileList(fileList,new File(path),depth,count);
        }
        ExecutorService service= Executors.newFixedThreadPool(threads);
        log.info("=============线程数量："+threads+",indexRoot："+indexRoot);
        ExecutorService subService= Executors.newFixedThreadPool(threads);
        for(File file:fileList){
            service.submit(new Runnable() {
                @SneakyThrows
                @Override
                public void run() {
                    FileOperation.find(fileTypes,file.getPath(),buildFileIndex,subService,totalList,list,indexName,docType);
                }
            });
        }
        service.shutdown();
        boolean flag=true;
        while(flag){
            Thread.sleep(10000);
            log.info("!!!!!!!!!!!!!!!!!!已扫描文件数量："+list.size()+" !!!!!!!!!!!!!!");
            if(service.isTerminated()){
                flag=false;
                subService.shutdown();
                boolean subFlag=true;
                while(subFlag){
                    Thread.sleep(10000);
                    if(totalList.size()==0){
                        continue;
                    }
                    long cost=System.currentTimeMillis()-start;
                    int remind=list.size()-totalList.size();
                    log.info("已索引文件数量："+totalList.size()+"，文件总数："+list.size()+"，剩余文件数量："+remind+"，已耗时："+ cost+"ms，预计剩余时间："+((cost/totalList.size())*remind)+"ms，请耐心等待！@^^@");
                    if(subService.isTerminated()){
                        log.info("======全文检索结束（fulltext is end）=======索引文件总数："+totalList.size()+"，总耗时："+(System.currentTimeMillis()-start)+"ms");
                        subFlag=false;
                    }
                }
            }
        }
    }

    /**
     * 获取目录或文件数量用于决定多线程的数量
     * @param fileList
     * @param file
     * @param depth：递归的深度
     * @param depth：递归的次数
     */
    public void getFileList(List<File> fileList,File file,int depth,int count){
        if(count<depth){
            count++;
            if(file.isDirectory()){
                File[] files=file.listFiles();
                if(files!=null&&files.length>0){
                    for(File f:files){
                        getFileList(fileList,f,depth,count);
                    }
                }
            }else{
                fileList.add(file);
            }
        }else{
            fileList.add(file);
        }
    }

}
